# -*- coding: utf-8 -*-
# ㊎ Author : XMZ
# ㊍ Date:  : 2024/09/06 上午11:35
# ㊌ File   : script-framework->requestPlus.py
# ㊋ IDE    : PyCharm
# ㊏ REMARKS:
import os
import sys
import logging
from pathlib import Path
from typing import Optional

import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import RequestException
from urllib3.util.retry import Retry

path = os.path.abspath(__file__)
sys.path.append(str(Path(__file__).absolute().parent.parent.parent))
from publics.packets import UserAgent
from core.config import settings


class RequestPlus:
    DEFAULT_RETRIES = 3  # 重试次数
    DEFAULT_BACKOFF_FACTOR = 0.3  # 重试之间的等待时间因子
    DEFAULT_STATUS_FORMALIST = (500, 502, 504)
    DEFAULT_TIMEOUT = 120  # 默认超时时间（秒）

    _session = None

    def __init__(self):
        """初始化HTTP会话和重试策略"""
        # 如果已创建，则重用会话
        if self._session is None:
            self._session = requests.Session()
            self._setup_retries_strategy(self._session)
        self.session = self._session

    @staticmethod
    def proxies(cls, override_proxy: Optional[str] = None):
        """获取代理，允许按请求覆盖。"""
        proxy = override_proxy or settings.proxy
        return {"http": proxy, "https": proxy} if proxy else None

    @staticmethod
    def _setup_retries_strategy(session: requests.Session):
        """配置重试策略和适配器"""
        retries_strategy = Retry(
            total=RequestPlus.DEFAULT_RETRIES,
            backoff_factor=RequestPlus.DEFAULT_BACKOFF_FACTOR,
            status_forcelist=RequestPlus.DEFAULT_STATUS_FORMALIST,
        )
        adapter = HTTPAdapter(max_retries=retries_strategy)
        session.mount('http://', adapter)
        session.mount('https://', adapter)

    @classmethod
    def get(cls, url, **kwargs) -> Optional[requests.Response]:
        """发送GET请求"""
        return cls().request(url=url, method='GET', **kwargs)

    @classmethod
    def post(cls, url, **kwargs) -> Optional[requests.Response]:
        """发送POST请求"""
        return cls().request(url=url, method='POST', **kwargs)

    def request(self, url: str, method: str, **kwargs) -> Optional[requests.Response]:
        """
        :param url: 必须传入的url
        :param method: 请求方法
        :param retries: 重试次数，默认为3次
        :param kwargs: 可选参数，如method、timeout、params等
        :return: 返回正常访问的内容或者返回None
        """
        headers = {'Accept': '*/*', 'User-Agent': UserAgent()}
        headers.update(kwargs.get('headers') or {})
        try:
            response = self.session.request(
                method=method,
                url=url,
                timeout=kwargs.get('timeout', self.DEFAULT_TIMEOUT),
                params=kwargs.get('params'),
                data=kwargs.get('data'),
                files=kwargs.get('files'),
                json=kwargs.get('json'),
                cookies=kwargs.get('cookies'),
                proxies=self.proxies(kwargs.get('proxy')),
                headers=headers,
                verify=kwargs.get('verify'),
            )
            response.raise_for_status()  # 如果响应状态不是200系列或300系列，直接抛出异常
            return response
        except RequestException as e:
            logging.error(f"根请求模块异常：{e}")
            return None
